import { Vector3, Spherical } from "three";
import { useEffect, useRef, useState } from "react";
import { useFrame, useThree } from "@react-three/fiber";
import { useKeyboardControls } from "@react-three/drei";
import {
  CapsuleCollider,
  RapierRigidBody,
  RigidBody,
} from "@react-three/rapier";
import { useModels } from "../../stores";
import { toFixed } from "../../utils";
import { START_POS, START_ROT } from "@/config";
import TWEEN, { Group } from "@tweenjs/tween.js";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";

const tweenGroup = new Group();

const SPEED = 2; // 移动速度
const JUMP = 1; // 跳力
const direction = new Vector3(); // 移动方向
const frontVector = new Vector3(); // 前后移动
const sideVector = new Vector3(); // 左右移动

let onGround = false; // 是否在地面
let init = true;
export function PovPlayer({ log = false }) {
  /*---------------------------声名变量-------------------------------*/
  const player = useRef<RapierRigidBody>(null);
  // 玩家在触摸屏的输入
  const { director, action, cameraTarget, setState } = useModels;
  const [, get] = useKeyboardControls();
  const { controls } = useThree();

  const [animate, setAnimate] = useState(false);

  useEffect(() => {
    return () => {
      // 清除所有 Tween 动画
      tweenGroup.removeAll();
    };
  }, []);

  useEffect(() => {
    setTimeout(() => {
      setState({
        cameraTarget: {
          position: new Vector3(6, 0, 6),
          target: new Vector3(15, 2, 15),
        },
      });
    }, 5000);
  }, []);

  useEffect(() => {
    if (!cameraTarget) return;
    cameraMoveTo(cameraTarget.position, cameraTarget.target);
  }, [cameraTarget]);

  /*---------------------------帧回调-------------------------------*/
  useFrame((state, delta) => {
    if (!player.current) return;

    // 获取键盘输入
    const { forward, backward, left, right, jump } = get();

    // 获取移动方向
    frontVector.set(0, 0, Number(backward) - Number(forward)); // 前后移动
    sideVector.set(Number(left) - Number(right), 0, 0); // 左右移动
    if (director) {
      direction
        .copy(director)
        .normalize()
        .multiplyScalar(SPEED)
        .applyEuler(state.camera.rotation); // 以相机方向为基准
    } else {
      direction
        .subVectors(frontVector, sideVector)
        .normalize()
        .multiplyScalar(SPEED)
        .applyEuler(state.camera.rotation); // 以相机方向为基准
    }

    // 跳跃
    if ((jump || action) && onGround) {
      onGround = false;
      player.current.applyImpulse({ x: 0, y: JUMP, z: 0 }, true);
    }
    // 移动
    const velocity = {
      x: toFixed(direction.x),
      y: player.current.linvel().y,
      z: toFixed(direction.z),
    };
    player.current.setLinvel(velocity, true);
    // 更新相机位置
    animate && tweenGroup.update();
    updateCamera(state, delta);
  });

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  function updateCamera(state: any, delta: number, distance: number = 0.1) {
    if (!player.current) return;

    const playerPos = player.current.translation(); // 玩家世界坐标

    const rotateDelta = (direction.x / 100) * delta;

    const { camera, controls } = state;
    controls.target.copy(playerPos);
    if (init) {
      init = false;
      controls.setAzimuthalAngle(START_ROT[1]);
      controls.setPolarAngle(START_ROT[0]);
    }

    const spherical = new Spherical(
      distance,
      controls.getPolarAngle(),
      controls.getAzimuthalAngle() - rotateDelta
    );
    const position = new Vector3().setFromSpherical(spherical);
    camera.position.copy(playerPos).add(position);
  }

  // 镜头移动动画——因为镜头绑定玩家所以只要移动玩家，然后让相机看向目标点
  function cameraMoveTo(to: Vector3, target: Vector3) {
    setAnimate(true);
    const playerPos = player.current!.translation();
    // 玩家新位置
    const cameraDirection = new Vector3().subVectors(target, to);
    const newPlayerPos = to.clone().add(cameraDirection.multiplyScalar(0.1));

    // 玩家位置
    new TWEEN.Tween(playerPos, tweenGroup)
      .to(newPlayerPos, 1500)
      .easing(TWEEN.Easing.Quartic.InOut)
      .start()
      .onUpdate(() => {
        player.current!.setTranslation(playerPos, false);
      })
      .onComplete(() => {
        setAnimate(false);
      });

    new TWEEN.Tween((controls as OrbitControls).target, tweenGroup)
      .to(target, 1500)
      .easing(TWEEN.Easing.Quartic.InOut)
      .onUpdate(() => {
        (controls as OrbitControls).update(); // 确保控制器在动画过程中更新
      })
      .start();
  }

  /*---------------------------模型渲染-------------------------------*/
  return (
    <RigidBody
      name="玩家"
      position={START_POS}
      ref={player}
      colliders={false}
      mass={1}
      type="dynamic"
      enabledRotations={[false, false, false]}
      onCollisionEnter={({ manifold, other }) => {
        const result = manifold.solverContactPoint(0);
        if (!result) return;

        onGround = true;
        if (other.rigidBodyObject && log) {
          console.log("碰撞点： ", result);
          console.log("碰撞对象：", other.rigidBodyObject.name);
        }
      }}
    >
      <CapsuleCollider args={[0.6, 0.2]} />
    </RigidBody>
  );
}
